/**
 unixSocket - implementation of Unix domain sockets
 
 $Id: unixSocket.h 2 2012-04-04 15:07:32Z gerhardus1@gmail.com $
 Versioning: a.b.c a is a major release, b represents changes or new features, c represents bug fixes. 
 @version 1.0.0   06/10/2011    Gerhardus Muller     Script created

 @note

 @todo
 
 @bug

 Copyright Gerhardus Muller
 */

#if !defined( unixSocket_defined_ )
#define unixSocket_defined_

#include "utils/object.h"
#include <sys/poll.h>

class unixSocket : public object
{
// Definitions
public:
//  typedef char                                char_type;
//  static const int READ_BUF_SIZE = 32768;
  static const int READ_BUF_SIZE = 4096;

// Methods
public:
	unixSocket( int fd, bool isudp=false, const char* name = "unixSocket" );
	virtual ~unixSocket();
  virtual std::string toString ();
  
  static void createSocketPair( int socketfd[2], const char* label=NULL );
  std::string read( );
  std::streamsize read(char* s, std::streamsize n);
  std::streamsize write(const char* s, std::streamsize n);
  static std::streamsize writeOnce( int fd, const std::string& s, bool bPipe=false );
  void setNonblocking( );
  void setNoSigPipe( );
  void returnUnusedCharacters( const char* buf, int n );
  int  getSocketFd( )                             {return socketfd;};
  bool isEof( )                                   {return bEof;};
  void resetEof( )                                {bEof=false;};
  void setUdp( )                                  {bUdp=true;};
  int  getPollTimeout(  )                         {return pollTimeout;};
  void setPollTimeout( int t )                    {pollTimeout=t;}; // timeout is in ms
  void setLogLevel( int l )                       {log.setNewLevel((loggerDefs::eLogLevel)l);}; // higher level logs more

//  bool waitForEvent( const sigset_t *sigmask=NULL );
  bool waitForEvent( );
  bool multiFdWaitForEvent( );
  void initPoll( int numFds );
  void resetPoll( )                               {pollFdCount=0;}
  int  getNextFd( );
  int  getLastErrorFd( )                          {return lastErrorFd;}
  void addReadFd( int fd );
  void setPipe( )                                 {bPipe=true;}
  void setThrowEof( )                             {bThrowEof=true;}
  
private:

// Properties
public:
    static logger*              pStaticLogger;              ///< class scope logger
    static logger               staticLogger;               ///< class scope logger

protected:

private:
    int                               socketfd;             ///< socket pair file descriptors
    bool                              bEof;                 ///< set to true on eof (socket closed) condition
    bool                              bUdp;                 ///< true for a udp type socket where the entire message must be read in one go
    bool                              bPipe;                ///< true if we are reading from a pipe
    bool                              bThrowEof;            ///< if true throw on read on eof
    struct pollfd*                    pollFd;               ///< poll fd structure
    int                               numPollFdEntries;     ///< number of entries in pollFd
    int                               numPollFdsProcessed;  ///< number of entries processed - <= numPollFdsAvailable
    int                               numPollFdsAvailable;  ///< number of fds with available data
    int                               lastFdProcessed;      ///< last fd that was processed
    int                               lastErrorFd;          ///< last fd with a detected error on it
    int                               pollFdCount;          ///< used to assemble the pollFd structure
    int                               pollTimeout;          ///< time that poll blocks
    std::string                       unusedChars;          ///< characters read from the socket and left over
};	// class unixSocket

#endif // !defined( unixSocket_defined_)

